package controller

import (
	"errors"

	"gitee.com/liuyun-luo/MagicStreamMovies/Server/global"
	"gitee.com/liuyun-luo/MagicStreamMovies/Server/models"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// 添加评论--并更新电影评分
func AddMovieReview(ctx *gin.Context) {
	var MovieReviewDTO struct {
		Review    string             `json:"review" binding:"required"`   //评论内容
		Rating    models.MovieRating `json:"rating" binding:"required"`   //用户给电影的评分
		LikeCount uint64             `json:"like_count"`                  //评论的点赞数量
		MovieId   uint               `json:"movie_id" binding:"required"` //评论的电影的id
		UserId    uint               `json:"user_id" binding:"required"`  //评论的用户的id
	}

	//获取参数
	if err := ctx.ShouldBindJSON(&MovieReviewDTO); err != nil {
		ctx.JSON(400, gin.H{
			"error": "参数错误,err: " + err.Error(),
		})
		return
	}

	//填充基础数据
	movie_review := models.MovieReview{
		Review:    MovieReviewDTO.Review,
		Rating:    MovieReviewDTO.Rating * 2, //翻一倍，因为用户只能选1-5
		LikeCount: MovieReviewDTO.LikeCount,
		MovieId:   MovieReviewDTO.MovieId,
		UserId:    MovieReviewDTO.UserId,
	}

	//启动事务
	err := global.MySQLDb.Transaction(func(tx *gorm.DB) error {
		//插入到数据库
		if err := tx.Create(&movie_review).Error; err != nil {
			return errors.New("插入数据库失败,err: " + err.Error())
		}

		//数据库层面，原子性地，把评分累加到电影的总评分
		err := tx.Model(&models.Movie{}).
			Where("id = ?", movie_review.MovieId).
			Updates(map[string]any{
				"rating":       gorm.Expr("(rating+?)/(review_count+?)", movie_review.Rating, 1),
				"review_count": gorm.Expr("review_count+?", 1),
			}).Error

		if err != nil {
			return errors.New("更新数据库失败,err: " + err.Error())
		}
		return nil
	})

	if err != nil {
		ctx.JSON(500, gin.H{
			"error": err.Error(),
		})
		return
	}

	//返回创建的电影的信息
	ctx.JSON(200, &movie_review)
}

// 获取评论--使用游标分页
func GetMovieReview(ctx *gin.Context) {
	movie_id := ctx.Param("movie_id")
	if movie_id == "" {
		ctx.JSON(400, gin.H{
			"error": "参数错误,电影id不能为空",
		})
		return
	}

	var ReviewInputDTO struct {
		//起始游标（本质是评论的ID，首次请求时可为0）
		Cursor uint `json:"cursor"`
		//请求的评论的数量
		PageSize uint `binding:"required" json:"page_size"`
		//排序方式
		SortBy string `json:"sort_by" binding:"required,oneof=like_count created_at"`
		//排序方向
		SortDirection string `json:"sort_direction" binding:"required,oneof=desc asc"`
		//发起请求的用户的id
		UserId uint `json:"user_id"`
	}


	//读取参数
	if err := ctx.ShouldBindJSON(&ReviewInputDTO); err != nil {
		ctx.JSON(400, gin.H{
			"error": "参数错误" + err.Error(),
		})
		return
	}
  
	// 构建基础查询
	query := global.MySQLDb.Model(&models.MovieReview{}).Where("movie_id = ?", movie_id)

	if ReviewInputDTO.Cursor != 0 { //不是第一次请求
		var review models.MovieReview
		//获取当前游标
		if err := global.MySQLDb.Where("id = ?", ReviewInputDTO.Cursor).First(&review).Error; err != nil {
			ctx.JSON(404, gin.H{
				"error": "该id的评论不存在" + err.Error(),
			})
			return
		}

		switch ReviewInputDTO.SortBy {
		case "like_count":
			if ReviewInputDTO.SortDirection == "desc" {
				query = query.Where("like_count < ? OR (like_count=? AND id >= ?)",
					review.LikeCount, review.LikeCount, ReviewInputDTO.Cursor)
			} else {
				query = query.Where("like_count > ? OR (like_count=? AND id >= ?)",
					review.LikeCount, review.LikeCount, ReviewInputDTO.Cursor)
			}
		case "created_at":
			if ReviewInputDTO.SortDirection == "desc" {
				query = query.Where("created_at < ? OR (created_at=? AND id >= ?)",
					review.LikeCount, review.LikeCount, ReviewInputDTO.Cursor)
			} else {
				query = query.Where("created_at > ? OR (created_at=? AND id >= ?)",
					review.LikeCount, review.LikeCount, ReviewInputDTO.Cursor)
			}
		default:
			query = query.Where("id >= ?", ReviewInputDTO.Cursor)
		}
	} else { //第一次请求
		query = query.Where("id >= ?", ReviewInputDTO.Cursor)
	}

	//应用排序
	query.Order(ReviewInputDTO.SortBy + " " + ReviewInputDTO.SortDirection)

	//限制查询的记录的最大条数
	query.Limit(int(ReviewInputDTO.PageSize) + 1)


	var MovieReviewList []models.MovieReview
	//执行查询
	if err := query.
		Preload("User", func(tx *gorm.DB) *gorm.DB {
			return tx.Select("name", "id") //注意：需要包含外键
		}).Find(&MovieReviewList).Error; err != nil {
		ctx.JSON(500, gin.H{
			"error": "评论查询失败" + err.Error(),
		})
		return
	}

	var nextCursor uint
	// 5. 处理结果，设置下一个游标
	if len(MovieReviewList) > int(ReviewInputDTO.PageSize) {
		// 有下一页，返回第input.PageSize条记录的ID作为下一个游标
		nextCursor = MovieReviewList[ReviewInputDTO.PageSize].ID
		MovieReviewList = MovieReviewList[:ReviewInputDTO.PageSize] // 截断结果
	} else {
		nextCursor = 0 // 没有下一页
	}

	ctx.JSON(200, gin.H{
		"movie_review_list": MovieReviewList,
		"next_cursor":       nextCursor,
	})
}
